﻿using LukasKopenec.LocalizationSupport;
using Notoric.Commanding.CommandBase;

namespace Notoric.ViewModel
{
    /// <summary>
    /// An undoable command for inserting a tone into a chord.
    /// </summary>
    /// <remarks>
    /// Input Parameters
    /// <list type="table">
    /// <listheader>
    /// <term>
    ///     Name
    /// </term>
    /// <description>
    ///     Description
    /// </description>
    /// </listheader>
    /// <item>
    /// <term>
    ///     <see cref="Chord"/> (<see cref="Model.Elements.ChordElement"/>)
    /// </term>
    /// <description>
    ///     The chord into which the tone is inserted.
    /// </description>
    /// </item>
    /// <item>
    /// <term>
    ///     <see cref="Tone"/> (<see cref="Model.Elements.Tone"/>)
    /// </term>
    /// <description>
    ///     The description of the inserted tone.
    /// </description>
    /// </item>
    /// </list>
    /// Output Parameters:
    /// <list type="table">
    /// <listheader>
    /// <term>
    ///     Name
    /// </term>
    /// <description>
    ///     Description
    /// </description>
    /// </listheader>
    /// <item>
    /// <term>
    ///     <see cref="CreatedTone"/> (<see cref="Model.Elements.ToneElement"/>)
    /// </term>
    /// <description>
    ///     The tone created by the command.
    /// </description>
    /// </item>
    /// </list>
    /// </remarks>
    public class AddToneCommand : UndoableCommandBase
    {
        #region Constructors

        /// <summary>
        /// Creates a new <see cref="AddToneCommand"/> instance.
        /// </summary>
        /// <param name="undoStack">
        /// <para>
        /// Type: <see cref="CommandStack"/>
        /// </para>
        /// <para>
        /// The command stack where the command will be put after its execution.
        /// </para>
        /// </param>
        /// <param name="redoStack">
        /// <para>
        /// The command stack where the command will be put when it has been undone.
        /// </para>
        /// </param>
        public AddToneCommand(CommandStack undoStack, CommandStack redoStack)
            : base(undoStack, redoStack)
        {
            AddParameter<Model.Elements.ChordElement>("Chord", ParameterDirection.In);
            AddParameter<Model.Elements.Tone>("Tone", ParameterDirection.In);

            AddParameter<Model.Elements.ToneElement>("CreatedTone", ParameterDirection.Out);

            Name = (string)LocalizationManager.GetValue("Commands.Names.AddTone");
        }

        #endregion

        #region Command Logic

        /// <inheritdoc/>
        protected override void CommandOperation(object parameter)
        {
            CreatedTone = Chord.AddTone(Tone);
            Chord.PackagePart.Package.IsModified = true;
        }

        /// <inheritdoc/>
        protected override void RedoOperation()
        {
            Chord.AddExistingTone(CreatedTone);
            Chord.PackagePart.Package.IsModified = true;
        }

        /// <inheritdoc/>
        protected override void UndoOperation()
        {
            Chord.RemoveTone(CreatedTone);
            Chord.PackagePart.Package.IsModified = true;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the chord to which the tone is inserted.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Model.Elements.ChordElement"/>
        /// </para>
        /// <para>
        /// The chord to which the tone is inserted.<br/>
        /// This property wraps the "Chord" command parameter.
        /// </para>
        /// </value>
        public Model.Elements.ChordElement Chord
        {
            get { return GetParameterValue<Model.Elements.ChordElement>("Chord"); }
            set { SetParameterValue<Model.Elements.ChordElement>("Chord", value); }
        }

        /// <summary>
        /// Gets the tone created by this command.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Model.Elements.ToneElement"/>
        /// </para>
        /// <para>
        /// The tone created by this command.<br/>
        /// This property wraps the "CreatedTone" command parameter.
        /// </para>
        /// </value>
        public Model.Elements.ToneElement CreatedTone
        {
            get { return GetParameterValue<Model.Elements.ToneElement>("CreatedTone"); }
            private set { SetParameterValue<Model.Elements.ToneElement>("CreatedTone", value); }
        }

        /// <summary>
        /// Gets or sets the description of the inserted tone.
        /// </summary>
        /// <value>
        /// <para>
        /// Type: <see cref="Model.Elements.Tone"/>
        /// </para>
        /// <para>
        /// The description of the inserted tone.<br/>
        /// This property wraps the "Tone" command parameter.
        /// </para>
        /// </value>
        public Model.Elements.Tone Tone
        {
            get { return GetParameterValue<Model.Elements.Tone>("Tone"); }
            set { SetParameterValue<Model.Elements.Tone>("Tone", value); }
        }

        #endregion
    }
}
